<?php

namespace RedMVC;

/**
 * Navigation class
 *  
 * @category    RedMVC
 * @author      Jan Fischer, bitWorking <info@bitworking.de>
 */
class Navigation{

    private static $data                = array();    
    private static $breadcrumbs         = array();

    public static function menu($data, $maxDepth = null, $ulClass = null, $onlyActiveBranch = false){
        $data = self::_getData($data);
        if(count($data) == 0){
            return '';
        }        
        self::$data = $data;
        self::setActiveRecursive(self::$data);
        return self::buildRecursive(self::$data, $maxDepth, 0, $ulClass, $onlyActiveBranch);
    }

    public static function breadcrumb($data, $delimiter = ' / '){
        $data = self::_getData($data);
        if(count($data) == 0){
            return '';
        }
        
        $page = self::findActive($data);
        if(null === $page){
            return '';
        }
        self::$breadcrumbs = array();
        self::getParentsRecursive($page);
        self::$breadcrumbs = array_reverse(self::$breadcrumbs);
        $out = '';
        foreach(self::$breadcrumbs as $parent){
            $out .= self::buildLink($parent).$delimiter;
        }
        $translate = Registry::get('RedMVC_Translate');
        $out .= '<span>'.$translate->_($page->name).'</span>';
        return $out;
    }

    public static function childs(Page $page, $data, $maxDepth = null, $ulClass = null){
        $data = self::_getData($data);
        if(count($data) == 0){
            return '';
        }
        $childs = self::getChilds($page, $data);
        if(count($childs) == 0){
            return '';
        }
        return self::buildRecursive($childs, $maxDepth, 0, $ulClass);
    }
    
    public static function raw($data){
        $data = self::_getData($data);
        if(count($data) == 0){
            return array();
        }        
        self::$data = $data;
        self::setActiveRecursive(self::$data);
        return self::$data;
    }
    
    private static function _getData($data){
        if(!is_array($data)){
            if(file_exists($data)){
                ob_start();
                $data = include($data);
                ob_end_clean();
            }
        }
        if(!is_array($data)){
            throw new \Exception("Navigation: data is no valid file or array");
        }
        return $data;
    }
    
    /* Menu *******************************************************************/
    
    public static function setActiveRecursive($pageArray){
        foreach($pageArray as $page){
            if(self::isActive($page)){
                $page->isActive = true;
                self::setParentActiveRecursive($page);
                return;
            }            
            if(count($page->getChilds()) > 0){
                self::setActiveRecursive($page->getChilds());
            }            
        }
    }
    
    public static function setParentActiveRecursive(Page $page){
        if(null !== $page->parent){
            $page->parent->isActive = true;
            self::setParentActiveRecursive($page->parent);
        }
    }
    
    public static function buildRecursive($pageArray, $maxDepth, $depth = 0, $ulClass = null, $onlyActiveBranch = false){
        $class = '';
        if(null !== $ulClass){
            $class = ' class="'.$ulClass.'"';
        }
        $out = '<ul'.$class.'>';
        foreach($pageArray as $page){
            $activeClass = '';
            if($page->isActive){
                $activeClass = ' class="active"';
            }
            if(!$page->isVisible){
                continue;
            }
            $link = self::buildLink($page);
            if(null === $link){
                continue;
            }
            $out .= '<li'.$activeClass.'>';
            $out .= $link;
            if(count($page->getChilds()) > 0 && (null === $maxDepth || $depth < $maxDepth)){
                if(!$onlyActiveBranch || $page->isActive){
                    $out .= self::buildRecursive($page->getChilds(), $maxDepth, $depth+1, null);
                }
            }
            $out .= '</li>';
        }
        $out .= '</ul>';
        return $out;
    }
    
    public static function buildLink(Page $page){
        $translate = Registry::get('RedMVC_Translate');
        if(null !== $page->uri){
            return '<a class="'.$page->cssClass.'" href="'.$page->uri.'" target="_blank">'.$translate->_($page->name).'</a>';
        }        
        $request    = Registry::get('RedMVC_Request');
        $router     = Registry::get('RedMVC_Router');
        // check acl
        $acl        = Registry::get('RedMVC_Acl');
        $aclRole    = Registry::get('RedMVC_Acl_Role');
        if(null !== $acl && null !== $aclRole){
            if(!$acl->isAllowed($aclRole, $page->resource, $page->privilege)){
                return null;
            }
        }
        return '<a class="'.$page->cssClass.'" href="'.$request->getBaseUrl().$router->buildUrl($page->controller, $page->action, $page->params).'">'.$translate->_($page->name).'</a>';
    }
    
    private static function isActive(Page $page){
        $request = Registry::get('RedMVC_Request');        
        if(($request->getControllerName() == $page->controller) && ($request->getActionName() == $page->action)){
            return true;
        }
        return false;
    }
    
    /* Breadcrumb *************************************************************/
    
    public static function findActive($pageArray){
        foreach($pageArray as $page){
            if(self::isActive($page)){
                return $page;                
            }
            if(count($page->getChilds()) > 0){
                $active = self::findActive($page->getChilds());
                if(null !== $active){
                    return $active;
                }
            }
        }
        return null;
    }
    
    public static function getParentsRecursive(Page $page){
        if(null !== $page->parent){
            self::$breadcrumbs[] = $page->parent;
            self::getParentsRecursive($page->parent);
        }
    }

    /* Childs *****************************************************************/

    public static function getChilds(Page $page, $pageArray){
        foreach($pageArray as $_page){
            if($_page->controller == $page->controller && $_page->action == $page->action){
                return $_page->getChilds();
            }
            if(count($_page->getChilds()) > 0){
                return self::getChilds($page, $_page->getChilds());
            }
        }
    }

}